package com.jiantong.web.open.app.work;

import com.google.common.collect.Maps;
import com.jiantong.web.core.enums.ExceptionCode;
import com.jiantong.work.dto.RetailImmunizationRecordDto;
import com.jiantong.work.model.RetailImmunizationRecord;
import com.jiantong.work.model.RetailImmunizationSubRecord;
import com.jiantong.work.service.RetailImmunizationRecordReadService;
import com.jiantong.work.service.RetailImmunizationRecordWriteService;
import com.jiantong.work.service.RetailImmunizationSubRecordReadService;
import io.terminus.boot.rpc.common.annotation.RpcConsumer;
import io.terminus.common.model.Paging;
import io.terminus.common.model.Response;
import io.terminus.pampas.openplatform.annotations.OpenBean;
import io.terminus.pampas.openplatform.annotations.OpenMethod;
import io.terminus.pampas.openplatform.exceptions.OPClientException;
import io.terminus.pampas.openplatform.exceptions.OPServerException;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Strings;
import org.joda.time.DateTime;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by mz on 20/9/17.
 *
 */
@Slf4j
@OpenBean
public class RetailImmunizationRecordApis {

    @RpcConsumer
    private RetailImmunizationRecordReadService retailImmunizationRecordReadService;

    @RpcConsumer
    private RetailImmunizationRecordWriteService retailImmunizationRecordWriteService;

    @RpcConsumer
    private RetailImmunizationSubRecordReadService retailImmunizationSubRecordReadService;

    @OpenMethod(
            key = "create.retail.immunization.record",
            paramNames = {"retailImmunizationRecordDto","toStatus"},
            httpMethods = RequestMethod.POST
    )
    public Long create(RetailImmunizationRecordDto retailImmunizationRecordDto ,Integer toStatus){
        RetailImmunizationRecord retailImmunizationRecord = retailImmunizationRecordDto.getRetailImmunizationRecord();
        if(retailImmunizationRecord == null){
            log.error("retailImmunizationRecord should be not null");
            throw new OPClientException(ExceptionCode.PARAMETER_NOT_EXIST.value(),"retailImmunizationRecord should be not null");
        }

        Response<Long> response = retailImmunizationRecordWriteService.create(retailImmunizationRecordDto,toStatus);

        if(!response.isSuccess()){
            log.error("failed to create this report , case = {}",response.getError());
            throw new OPServerException(ExceptionCode.DATA_WRITE_FAIL.value(),response.getError());
        }

        return response.getResult();
    }

    @OpenMethod(
            key = "update.retail.immunization.record",
            paramNames = {"retailImmunizationRecordDto","toStatus"},
            httpMethods = RequestMethod.PUT
    )
    public Boolean update(RetailImmunizationRecordDto retailImmunizationRecordDto ,Integer toStatus){
        RetailImmunizationRecord retailImmunizationRecord = retailImmunizationRecordDto.getRetailImmunizationRecord();
        if(retailImmunizationRecord == null){
            log.error("retailImmunizationRecord should be not null");
            throw new OPClientException(ExceptionCode.PARAMETER_NOT_EXIST.value(),"retailImmunizationRecord should be not null");
        }
        if(retailImmunizationRecord.getId() == null){
            log.error("id should be not null");
            throw new OPClientException(ExceptionCode.ID_NOT_EXIST.value(),"id should be not null");
        }

        if(retailImmunizationRecord.getStatus() == null){
            log.error("status should be not null");
            throw new OPClientException(ExceptionCode.PARAMETER_NOT_EXIST.value(),"status should be not null");
        }

        Response<Map<String , Integer>> mapResponse = retailImmunizationRecordReadService.findStatusById(retailImmunizationRecord.getId());
        if(mapResponse.isSuccess() && !retailImmunizationRecord.getStatus().equals(mapResponse.getResult().get("status"))){
            log.error("retailImmunizationRecord is already submitted");
            throw new OPClientException(ExceptionCode.DOCUMENT_REPEAT_SUBMIT.value(),"retailImmunizationRecord is already submitted");
        }

        Response<Boolean> response = retailImmunizationRecordWriteService.update(retailImmunizationRecordDto,toStatus);
        if(!response.isSuccess()){
            log.error("failed to update this report , case = {}",response.getError());
            throw new OPServerException(ExceptionCode.DATA_WRITE_FAIL.value(),response.getError());
        }

        return response.getResult();
    }

    @OpenMethod(
            key = "find.retail.immunization.record",
            paramNames = {"id"},
            httpMethods = RequestMethod.GET
    )
    public RetailImmunizationRecordDto findById(Long id){
        if(id == null){
            log.error("id should be not null");
            throw new OPClientException(ExceptionCode.ID_NOT_EXIST.value(),"id should be not null");
        }

        Response<RetailImmunizationRecord> recordResponse = retailImmunizationRecordReadService.findById(id);

        if(!recordResponse.isSuccess()){
            log.error("failed to find this report by id = {} , case = {}",id,recordResponse.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),recordResponse.getError());
        }

        Response<List<RetailImmunizationSubRecord>> listResponse = retailImmunizationSubRecordReadService.queryListByVaccineId(id);
        if(!listResponse.isSuccess()){
            log.error("failed to find this sub report by id = {} , case = {}",id,listResponse.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),listResponse.getError());
        }

        RetailImmunizationRecordDto retailImmunizationRecordDto = new RetailImmunizationRecordDto();
        retailImmunizationRecordDto.setRetailImmunizationRecord(recordResponse.getResult());
        retailImmunizationRecordDto.setVaccines(buildVaccines(listResponse.getResult()));

        return retailImmunizationRecordDto;
    }

    @OpenMethod(
            key = "paging.retail.immunization.record.for.a.single",
            paramNames = {"pageNo","pageSize","breedFactoryId","status"},
            httpMethods = RequestMethod.GET
    )
    public Paging<RetailImmunizationRecordDto> paging(Integer pageNo, Integer pageSize,
                                                   Long breedFactoryId,Integer status){
        if(breedFactoryId == null){
            log.error("breedFactoryId should be not null");
            throw new OPClientException(ExceptionCode.ID_NOT_EXIST.value(),"breedFactoryId should be not null");
        }

        Response<Paging<RetailImmunizationRecord>> response = retailImmunizationRecordReadService.paging(pageNo,pageSize,breedFactoryId,status);
        if(!response.isSuccess()){
            log.error("failed to do paging this factory reports , case = {}",response.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),response.getError());
        }

        List<RetailImmunizationRecordDto> retailImmunizationRecordDtos = new ArrayList<>();
        RetailImmunizationRecordDto retailImmunizationRecordDto = null;
        List<RetailImmunizationRecord> retailImmunizationRecords = response.getResult().getData();
        for(RetailImmunizationRecord retailImmunizationRecord : retailImmunizationRecords){
            Long vaccineId = retailImmunizationRecord.getId();
            Response<List<RetailImmunizationSubRecord>> response1 = retailImmunizationSubRecordReadService.queryListByVaccineId(vaccineId);
            if(!response1.isSuccess()){
                log.error("failed to query list case = {}",response1.getError());
                throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),response1.getError());
            }
            retailImmunizationRecordDto = new RetailImmunizationRecordDto();
            retailImmunizationRecordDto.setVaccines(buildVaccines(response1.getResult()));
            retailImmunizationRecordDto.setRetailImmunizationRecord(retailImmunizationRecord);
            retailImmunizationRecordDtos.add(retailImmunizationRecordDto);
        }

        Paging<RetailImmunizationRecordDto> paging = new Paging<>();
        paging.setTotal(response.getResult().getTotal());
        paging.setData(retailImmunizationRecordDtos);
        return paging;
    }

    @OpenMethod(
            key = "paging.retail.immunization.record.for.multi",
            paramNames = {"pageNo","pageSize","fromDate","toDate","breedType","villageId","breedFactoryId","status"},
            httpMethods = RequestMethod.GET
    )
    public Paging<RetailImmunizationRecordDto> pagingForMulti(Integer pageNo , Integer pageSize,
                                                           String fromDate , String toDate,
                                                           Integer breedType , Long villageId,
                                                           Long breedFactoryId , Integer status){
        Date start = null;
        if(!Strings.isNullOrEmpty(fromDate)){
            start = DateTime.parse(fromDate).toDate();
        }

        Date end = null;
        if(!Strings.isNullOrEmpty(toDate)){
            end = DateTime.parse(toDate).toDate();
        }

        Response<Paging<RetailImmunizationRecord>> response =
                retailImmunizationRecordReadService.pagingForMulti(pageNo,pageSize,start,end,breedType,villageId,breedFactoryId,status);

        if(!response.isSuccess()){
            log.error("failed to paging for multi, case = {}",response.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),response.getError());
        }

        List<RetailImmunizationRecordDto> retailImmunizationRecordDtos = new ArrayList<>();
        RetailImmunizationRecordDto retailImmunizationRecordDto = null;
        List<RetailImmunizationRecord> retailImmunizationRecords = response.getResult().getData();
        for(RetailImmunizationRecord retailImmunizationRecord : retailImmunizationRecords){
            Long vaccineId = retailImmunizationRecord.getId();
            Response<List<RetailImmunizationSubRecord>> response1 = retailImmunizationSubRecordReadService.queryListByVaccineId(vaccineId);
            if(!response1.isSuccess()){
                log.error("failed to query list case = {}",response1.getError());
                throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),response1.getError());
            }
            retailImmunizationRecordDto = new RetailImmunizationRecordDto();
            retailImmunizationRecordDto.setVaccines(buildVaccines(response1.getResult()));
            retailImmunizationRecordDto.setRetailImmunizationRecord(retailImmunizationRecord);
            retailImmunizationRecordDtos.add(retailImmunizationRecordDto);
        }

        Paging<RetailImmunizationRecordDto> paging = new Paging<>();
        paging.setTotal(response.getResult().getTotal());
        paging.setData(retailImmunizationRecordDtos);
        return paging;
    }


    private List<Map<String,Object>> buildVaccines(List<RetailImmunizationSubRecord> result) {
        if(result == null || result.isEmpty()){
            return null;
        }
        List<Map<String , Object>> vaccines = new ArrayList<>();
        for(RetailImmunizationSubRecord retailImmunizationSubRecord : result){
            Map<String , Object> map = Maps.newHashMap();

            map.put("id",retailImmunizationSubRecord.getId());
            map.put("vaccineId",retailImmunizationSubRecord.getVaccineId());
            map.put("breedSecondType",retailImmunizationSubRecord.getBreedSecondType());
            map.put("vaccineType",retailImmunizationSubRecord.getVaccineType());
            map.put("otherType",retailImmunizationSubRecord.getOtherType());
            map.put("vaccineCode",retailImmunizationSubRecord.getVaccineCode());
            map.put("vaccineName",retailImmunizationSubRecord.getVaccineName());
            map.put("date",retailImmunizationSubRecord.getDate());
            map.put("days",retailImmunizationSubRecord.getDays());
            map.put("times",retailImmunizationSubRecord.getTimes());
            map.put("quantity",retailImmunizationSubRecord.getQuantity());
            map.put("drugQuantity",retailImmunizationSubRecord.getDrugQuantity());
            map.put("method",retailImmunizationSubRecord.getMethod());
            map.put("drugUnit",retailImmunizationSubRecord.getDrugUnit());
            map.put("manufacturer",retailImmunizationSubRecord.getManufacturer());
            map.put("batch",retailImmunizationSubRecord.getBatch());
            map.put("operatorName",retailImmunizationSubRecord.getOperatorName());
            //反射
//            Class thisClass = retailImmunizationSubRecord.getClass();
//            Field[] fields = thisClass.getDeclaredFields();
//            for(Field field : fields){
//                field.setAccessible(true);
//                try {
//                    map.put(field.getName(),field.get(retailImmunizationSubRecord));
//                } catch (IllegalAccessException e) {
//                    e.printStackTrace();
//                }
//            }
            vaccines.add(map);
        }
        return vaccines;
    }
}
